// 封装ajax请求
import axios, { AxiosError, AxiosRequestConfig } from "axios";
import { nativeStorage, showToast } from "zmp-sdk";

// import JSONBig from 'json-bigint';

type AxiosType = "get" | "post" | "put" | "delete";
type requestConfig = {
  loading: boolean;
};
/** 正在进行中的请求列表 */
let reqList: { umet: string; cancel: (msg?: string) => void }[] = [];
/**
 * 阻止重复请求
 * @param {array} reqList - 请求缓存列表
 * @param {string} url - 当前请求地址
 * @param {function} cancel - 请求中断函数
 * @param {string} errorMessage - 请求中断时需要显示的错误信息
 */
const stopRepeatRequest = function (
  reqList: any[],
  config: any,
  cancel: (m?: string) => void
): void {
  const errorMsg = "Axios error info: 重复请求中断" + config.url;
  for (let i = 0; i < reqList.length; i++) {
    if (reqList[i].umet === config.url + "&" + config.method) {
      cancel(errorMsg);
      return;
    }
  }
  reqList.push({ umet: config.url + "&" + config.method, cancel });
};
/**
 * 取消请求操作
 * @param {array} reqList 全部请求列表
 * @param {string} url 请求地址
 */
const removeSource = function (reqList: any[], config: any): void {
  for (let i = 0; i < reqList.length; i++) {
    if (reqList[i].umet === config.url + "&" + config.method) {
      // reqList[i].cancel('取消请求');
      reqList.splice(i, 1);
      break;
    }
  }
};

export default function request<T>(
  url = "",
  data?: T,
  type: AxiosType = "get",
  config?: requestConfig
) {
  return new Promise((resolve, reject) => {
    if (config?.loading) {
      // showLoadingToast({
      //   // 开启loading
      //   message: "加载中...",
      //   forbidClick: true,
      // });
    }
    let p = null;
    // const axiosConfig: AxiosRequestConfig = {
    // 	transformResponse: [
    // 		function (data) {
    // 			// 由于后端返回的数据有出现大数问题（文章编号）,这里使用json-bigint处理一下
    // 			// 优先使用JSONBig转一下
    // 			try {
    // 				return JSONBig.parse(data); // 字符串--->对象
    // 			} catch (err) {
    // 				return data;
    // 			}
    // 		},
    // 	],
    // };
    if (type === "post" || type === "put") {
      p = axios({ method: type, url, data });
    }
    if (type === "delete" || type === "get") {
      p = axios({ method: type, url, params: data });
    }
    p?.then(function (response: any) {
      resolve(response.data);
    }).catch(function (error: any) {
      reject(error);
    });
  });
}

/** 请求拦截器 */
axios.interceptors.request.use(
  (config) => {
    let cancel;
    // 在发送请求之前做些什么
    if (nativeStorage.getItem("token")) {
      // @ts-ignore
      config.headers.token = nativeStorage.getItem("token");
    }
    // 设置cancelToken对象
    config.cancelToken = new axios.CancelToken(function (c) {
      cancel = c;
    });
    // 阻止重复请求。当上个请求未完成时，相同的请求不会进行
    stopRepeatRequest(reqList, config, cancel);
    return config;
  },
  (err) => Promise.reject(err) // 对请求错误做些什么
);
/** 添加响应拦截器 */
axios.interceptors.response.use(
  function (response: any) {
    // 请求结束后将对应存储的取消函数删除
    removeSource(reqList, response.config);
    // 关闭loading
    // closeToast();
    // 自定义错误处理
    const res = response.data;
    if (res.code === 401) {
      console.warn("Warning info: 状态码401，权限过期，请重新登录");
      reqList.forEach((item) => {
        item.cancel("401状态取消后续请求");
      });
      reqList = [];
      /** 当有401时，中断后续请求 */
      showToast({
        message: res.msg,
      });
      // router.push("/login"); // 到登录页重新登陆
      return response;
    }
    // if (res.code !== 200) {
    // 	// Toast(res.msg)
    // 	showToast({
    // 		type: 'fail',
    // 		message: '统一请求错误提示',
    // 		iconSize: 36,
    // 		duration: 3000,
    // 	});
    // }
    return response;
  },
  function (error: AxiosError) {
    if (axios.isCancel(error)) {
      // console.warn('Axios Warning info：' + error.message);
    } else {
      // 增加延迟，相同请求不得在短时间内重复发送
      setTimeout(() => {
        removeSource(reqList, error.config);
      }, 1000);
    }
    // 对响应错误做点什么
    const { message } = error;
    // setTimeout(() => {
    // 	showToast({
    // 		type: 'fail',
    // 		message,
    // 		iconSize: 36,
    // 		duration: 3000,
    // 	});
    // }, 0);

    return Promise.reject(error);
  }
);
